import sys
import pyglet
import random
import threading
import time 


class Player :
	"""This class manage the player, the playlist and simples options about the player
	"""
	def __init__(self) :
		self.__player = pyglet.media.Player()
		self.__isPlaying = False
		self.__playlist = []
		#length of the playlist (nbr of songs)
		self.__lenPlaylist = 0
		#current music on the playlist
		self.__current = 0
		self.__currentPath = None
		#options
		self.random = False
		self.repeat = False
		self.repeatAll = False
		self.__thread=threading.Thread(  group=None, target=self.fonction_thread, name=None, args=(), kwargs={})
		self.__wantToContinue = True
	
	def start(self) :
		if self.__wantToContinue :
			self.__thread.start()

		
	def close(self) :
		self.__wantToContinue = False
		self.__thread.join()
		
	def fonction_thread(self):
		sec = 0
		while self.__wantToContinue :
			self.__loop()
			try :
				secC = int(self.getPlayedDuration())
				if  secC != sec :
					#print secC
					sec = secC
			except Exception as e:
				e =""
				#print e
			time.sleep(0.05)
				

	#add a song in the playlist
	#if the position is not given, the song is add at the end of the list
	def add(self, PathFich, position = -1) :
		if position < 0:
			self.__playlist.append(PathFich)
			self.__lenPlaylist += 1
		else :
			if position >= self.__lenPlaylist :
				raise IndexError("The position to add the song is over the length of the playlist")
			self.__playlist.insert(position, PathFich)
			self.__lenPlaylist += 1
			if position <= self.__current :
				self.__changeCurrentSong(self.__current + 1)
		
	def loadPlaylist(self, fich) :
		try :
			fd=open(fich,'r')
		except :
			raise IOError("Une erreur est survenue lors de la lecture du fichier playlist.")
		for ligne in fd :
			self.add(ligne.rstrip())
		
	def savePlaylist(self, fich) :
		try :
			fd=open(fich,'w')
		except :
			raise IOError("Une erreur est survenue lors de la creation du fichier playlist.")
		for x in self.__playlist :
			fd.write("%s\n" % (x))

	#remove a song in the playlist
	def remove(self, position) :
		if position >= 0 and position < self.__lenPlaylist :
			if position <= self.__current :
				try :
					self.__changeCurrentSong(self.__current - 1)
				except IndexError :
					self.__current = 0
			self.__playlist.pop(position)
			self.__lenPlaylist -= 1

	#return the playlist	
	def getPlaylist(self):
		return self.__playlist

	#delete all the old playlist and set a new playlist		
	def setPlaylist(self, newPlaylist, newCurrent = 0) :
		lenNewPl = len(newPlaylist)
		if lenNewPl == 0 :
			return
		if newCurrent < 0 or newCurrent >= lenNewPl :
			newCurrent = 0
		self.__playlist = newPlaylist
		self.__lenPlaylist = lenNewPl
		self.stop()
		self.play()
	
	#play the playlist
	def play(self) :
		if self.__lenPlaylist != 0 :
			if self.__player.source == None :
				try :
					self.__runSong(self.__playlist[self.__current])
				except ValueError as e:
					print e
			self.__isPlaying = True
	def pause(self) :
		self.__isPlaying = False
	def stop(self) :
		self.pause()
		self.__currentPath = None
		self.__player.next()


	
	#function to call on a loop (threader ?)
	def __loop(self) :
		if self.__isPlaying :
			if self.__player.source == None and self.__lenPlaylist != 0 :
				if self.__current + 1 == self.__lenPlaylist and (not self.repeatAll) :
					self.pause()
					self.__current = 0
				else :
					self.next()
			self.__player.play()

	#go to the next song		
	def next(self) :
		self.goToSong(self.__current + 1, True)
	
	#go to the previous song
	def previous(self) :
		self.goToSong(self.__current - 1, True)
	
	#go to a song in the playlist
	#set respectOptions to False to disable shuffle, repeat and repeat all modes
	def goToSong(self, position, respectOptions = False) :
		self.stop()
		try :
			self.__changeCurrentSong(position, respectOptions)
			self.__runSong(self.__playlist[self.__current])
			self.play()
		except IndexError :
			pass
		except ValueError as e:
			print e
			self.next()

	#go to a second in the song
	def goToTime(self, seconds) :
		self.__player.seek(seconds)
	
	def setVolume(self, value) :
		self.__player.volume = value

	def getVolume(self) :
		return self.__player.volume
	
	def getPlayedDuration(self) :
		return self.__player.time
		
	def getCurrentSongDuration(self) :
		return self.__player.source.duration
		
	def getCurrentSongPath(self) :
		if self.__player.source != None :
			return self.__currentPath
		
	"""load a song on the Pyglet player
	can raise valueError exceptions"""		
	def __runSong(self, pathFich) :
		self.pause()
		try :
			fich = pyglet.media.load(pathFich)
			self.__currentPath = pathFich
			self.__player.queue(fich)
		except pyglet.media.avbin.AVbinException :
			raise ValueError("Invalid File. Can't play it.")
			self.__currentPath = None

	"""change the current song.
	If respectOptions is False, the play mode will be ignored.
	Can raise IndexError exceptions"""
	def __changeCurrentSong(self, newCurrent, respectOptions = True) :
		if self.__lenPlaylist == 0 :
			self.__current = 0
			self.pause()
			raise IndexError("the playlist is empty.")
		if respectOptions :
			if self.repeat :
				return
			if self.random :
				self.__current = random.randint(0,self.__lenPlaylist)
				return
			if self.repeatAll :
				self.__current = newCurrent % self.__lenPlaylist
				return

		if newCurrent < 0 or newCurrent >= self.__lenPlaylist :
			raise IndexError("current cursor out of playlist.")
		self.__current = newCurrent
		return True


#create a player referenced in a global variable (accessible in the main program and in the thread)
player = Player()

"""
#Test
#This test can't yet manage options of the player
while True :
	x=raw_input("Tapez qq chose : ")
	if x == "start" :
		player.start()
	if x == "close" :
		player.close()
	if x == "add" :
		y = raw_input("Nom : ")
		z = input("Pos : ")
		player.add(y, z)
	if x == "remove" :
		
		y = input("Num : ")
		player.remove(y)
	if x == "svg" :
		y = raw_input("Nom : ")
		player.savePlaylist(y)
	if x == "load" :
		y = raw_input("Nom : ")
		player.loadPlaylist(y)
	if x == "pause" :
		player.pause()
	if x == "play" :
		player.play()
	if x == "stop" :
		player.stop()
	if x == "quit" or x == "exit" :
		player.close()
		sys.exit()
	if x == "next" :
		player.next()
	if x == "previous" :
		player.previous()
	if x == "goToTime" :
		y = input("Duree :")
		player.goToTime(y)
	if x == "goToSong" :
		y = input("num :")
		player.goToSong(y)
	if x == "name" :
		print player.getCurrentSongName()
	if x == "time" :
		print player.getPlayedDuration(), player.getCurrentSongDuration()
	if x == "volume" :
		print player.getVolume()
	if x == "setVolume" :
		y = input("Volume :")
		player.setVolume(y)
#\Test"""
